#!/usr/bin/python
#+------------------------------------------------------------------------------
#|
#| FILENAME: gendocs.py
#|
#| PROJECT: Cairo Libraries
#|
#| FILE DESCRIPTION:
#|    This script is used to generate the documentation for the Cairo Libraries
#|    package.
#|
#+------------------------------------------------------------------------------
#|
#| Cairolib is a series of extensions, examples, and libraries for the
#| Cairo graphics package (see http://www.cairographics.org).
#| 
#| Copyright (C) 2006  Bradford Elliott
#|
#| This library is free software; you can redistribute it and/or
#| modify it under the terms of the GNU Lesser General Public
#| License as published by the Free Software Foundation; either
#| version 2.1 of the License, or (at your option) any later version.
#| 
#| This library is distributed in the hope that it will be useful,
#| but WITHOUT ANY WARRANTY; without even the implied warranty of
#| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#| Lesser General Public License for more details.
#| 
#| You should have received a copy of the GNU Lesser General Public
#| License along with this library; if not, write to the Free Software
#| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#| 
#+------------------------------------------------------------------------------
import sys
import re
import string
from string import Template;


#+-----------------------------------------------------------------------------
#|
#| HTML Template for generated documentation
#|
#+-----------------------------------------------------------------------------
html = string.Template(
"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!--
#+------------------------------------------------------------------------------
#|
#| Cairolib is a series of extensions, examples, and libraries for the
#| Cairo graphics package (see http://www.cairographics.org).
#| This library is free software; you can redistribute it and/or
#| modify it under the terms of the GNU Lesser General Public
#| License as published by the Free Software Foundation; either
#| version 2.1 of the License, or (at your option) any later version.
#| 
#| This library is distributed in the hope that it will be useful,
#| but WITHOUT ANY WARRANTY; without even the implied warranty of
#| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#| Lesser General Public License for more details.
#| 
#| You should have received a copy of the GNU Lesser General Public
#| License along with this library; if not, write to the Free Software
#| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#|
#+------------------------------------------------------------------------------
-->
<html>
<head>
    <title>$title</title>
    <link rel="stylesheet" type="text/css" media="all" href="docs/html/css/theme.css" title="Default" />
</head>
<body>
<div class="container">
    <div class="header">
        ...
    </div>
    <div class="body">
        $contents
    </div>
</div>
</body>
</html>
""");


#+-----------------------------------------------------------------------------
#|
#| FUNCTION:
#|    format_python()
#|
#| DESCRIPTION:
#|    This method is called to format a snippet of python within a section
#|    of a source document.
#| 
#| PARAMETERS:
#|    source (I) - The block of python source that is being formatted.
#| 
#| RETURNS:
#|    The block of python source code formatted as HTML.
#|
#+-----------------------------------------------------------------------------
def format_python(source):
    lines = source.split('\n')
    output = "<div style='margin-left: 30px; width: 70%; background-color: #F0F0F0; border: 1px solid #C0C0C0;'>"
    
    for line in lines:
        wspace = re.compile(" ")
        output += "<div style=''>" + wspace.sub("&nbsp;", line) + "</div>"
    
    return output + '</div>';


#+-----------------------------------------------------------------------------
#|
#| FUNCTION:
#|    format_code()
#|
#| DESCRIPTION:
#|    This method is called to format a block of generic code encountered
#|    within a "code" section of a source document.
#|
#| PARAMETERS:
#|    source (I) - The block of unknown source code that is being formatted.
#|
#| RETURNS:
#|    The block of unknown source code formatted as HTML.
#|
#+-----------------------------------------------------------------------------
def format_code(source):
    lines = source.split('\n')
    output = "<div style='font-family: courier; font-size: 0.8em; margin-left: 30px; width: 80%; background-color: #F0F0F0; border: 1px solid #C0C0C0;'>"
    
    for line in lines:
        wspace = re.compile(" ")
        output += "<div style=''>" + wspace.sub("&nbsp;", line) + "</div>"
    
    return output + '</div>';


#+-----------------------------------------------------------------------------
#|
#| FUNCTION:
#|    output_tag()
#|
#| DESCRIPTION:
#|    This method is called to parse a documentation tag and convert it to
#|    the appropriate output HTML format.
#| 
#| PARAMETERS:
#|    tag  (I) - The name of the input tag
#|    data (I) - The data attached to the input tag.
#|
#| RETURNS:
#|    The documentation tag formatted as HTML.
#|
#+-----------------------------------------------------------------------------
def output_tag(tag, data):
    
    # First make any links
    named_links = re.compile("\[\[(.*?),(.*?)\]\]")
    data = named_links.sub("<a href='\\1'>\\2</a>", data)
    links = re.compile("\[\[(.*?)\]\]")
    data = links.sub("<a href='\\1'>\\1</a>", data)
    
    
    if(tag == "h1"):
        return "<h1>" + data + "<a name='" + data + "'></a></h1>\n"
    elif(tag == "h2"):
        return "<h2>" + data + "<a name='" + data + "'></a></h2>\n"
    elif(tag == "h3"):
        return "<h3>" + data + "<a name='" + data + "'></a></h3>\n"
    elif(tag == "title"):
        return data
    elif(tag == "python"):
        return format_python(data)
    elif(tag == "code"):
        return format_code(data)
    elif(data != "" and data != "\n"):
        return "<p>" + data + "</p>\n"
    else:
        return ""


#+-----------------------------------------------------------------------------
#|
#| FUNCTION:
#|    generate_document()
#| 
#| DESCRIPTION:
#|    This is a fairly simplistic parser used to parse the contents of an
#|    input source document and convert it to output HTML.
#|
#| PARAMETERS:
#|    source_file (I) - The path to the input source document to convert
#|                      to HTML.
#|    output_file (I) - The output HTML file to create from the source
#|                      document.
#|
#| RETURNS:
#|    None.
#+-----------------------------------------------------------------------------
def generate_document(source_file, output_file):
    vars = {}
    
    source = open(source_file, "r")
    input = source.read()
    source.close()
    toc = False
    
    # First parse the document header
    header = re.compile("@title (.*?)\n.*?(@toc (yes|no))?.*?@body.", re.DOTALL | re.IGNORECASE)
    matches = header.search(input)
    if(matches):
        title = matches.groups()[0]
        if(len(matches.groups()) >= 2 and matches.groups()[2] == "yes"):
            toc = True
    else:
        print "Document header is invalid"; sys.exit(1)
    
    # Now parse the document body
    start = matches.end()
    
    contents = ""
    
    STATE_NORMAL     = 0
    STATE_INTAG      = 1
    STATE_INMTAGDATA = 2
    STATE_INTAGDATA  = 3
    STATE_ESCAPE     = 4
    STATE_COMMENT    = 5
    
    state = STATE_NORMAL
    saved_state = state
    
    tag_name = ""
    tag_data = ""
    
    for i in range(start, len(input)):
        
        if(state == STATE_INTAG):
            
            if(input[i] == ' ' or input[i] == '\t'):
                state = STATE_INTAGDATA
            elif(input[i] == '+'):
                state = STATE_INMTAGDATA
            else:
                tag_name += input[i];
            
        elif(state == STATE_INTAGDATA):
            if(input[i] == '#'):
                saved_state = state
                state = STATE_COMMENT
                
            elif(input[i] == '\n'):
                contents += output_tag(tag_name, tag_data)
                tag_name = ""
                tag_data = ""
                state = STATE_NORMAL
            elif(input[i] == '\\'):
                saved_state = state
                state = STATE_ESCAPE
            else:
                tag_data += input[i]
        
        elif(state == STATE_INMTAGDATA):
            if(input[i] == '#'):
                saved_state = state
                state = STATE_COMMENT
                
            elif(input[i] == '@'):
                contents += output_tag(tag_name, tag_data)
                tag_name = ""
                tag_data = ""
                state = STATE_NORMAL
            elif(input[i] == '\\'):
                saved_state = state
                state = STATE_ESCAPE
            else:
                tag_data += input[i]
            
        elif(state == STATE_NORMAL):
            if(input[i] == '#'):
                saved_state = state
                state = STATE_COMMENT
                
            elif(input[i] == '@'):
                contents += output_tag(tag_name, tag_data)
                
                tag_name = ""
                tag_data = ""
                
                state = STATE_INTAG;
            elif(input[i] == '\\'):
                saved_state = state
                state = STATE_ESCAPE
            else:
                tag_data += input[i];
        
        elif(state == STATE_ESCAPE):
            state = saved_state
            tag_data += input[i];
        
        elif(state == STATE_COMMENT):
            if(input[i] == '\n'):
                state = saved_state
    
    
    if(tag_data != ""):
        contents += output_tag("p", tag_data)
    
    vars["title"] = title
    vars["contents"] = contents
    
    output = open(output_file, "w")
    output.write(html.substitute(vars))
    output.close()


generate_document("source/installation.tpl", "../install.html")
generate_document("source/readme.tpl",       "../readme.html")


